package com.bana.fvs.service;

import com.bana.fvs.code.*;
import com.bana.fvs.dao.*;
import com.bana.fvs.model.*;
import com.bana.fvs.protocol.*;
import com.bana.fvs.task.SocketTask;
import com.bana.sys.code.SendResult;
import com.bana.sys.model.Department;
import com.bana.fvs.protocol.Shoot;
import com.bana.sys.service.CodeService;
import com.bana.sys.service.LogService;
import com.bana.sys.socket.SocketResult;
import com.bana.sys.utils.Convert;
import com.bana.sys.utils.Token;
import com.bana.sys.utils.Tuple;
import onbon.bx05.area.unit.StringBxUnit;
import org.omg.CORBA.INTERNAL;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class ControllerService {

    @Resource
    private FogAreaDAO fogAreaDAO;

    @Resource
    private ControllerDAO controllerDAO;

    @Resource
    private LampAddressDAO lampAddressDAO;

    @Resource
    private ControllerTextDAO controllerTextDAO;

    @Resource
    private StrategyDAO strategyDAO;

    @Resource
    private CodeService codeService;

    @Resource
    private LogService logService;

    /**
     * 控制器缓存，键为控制器编码，值为控制器缓存
     */
    private static Map<Integer,Controller> ControllerMap =new ConcurrentHashMap<>();

    /**
     * 控制器测试次数，键为控制器编码
     */
    private static Map<Integer, Integer> TestMap = new ConcurrentHashMap<>();

    /**
     * 雾灯缓存,在04协议，雾灯通知的时候保存到这个变量
     * 04协议可以获取雾灯最新的状态，而查询到的状态是滞后的状态，所以用通知的覆盖查询的，
     * 但是因为不稳定，暂时注释，现在还是以查询为准
     * 控制器编码,雾灯编号,是否碰撞
     */
    private static Map<String,Map<Integer,Integer>> LampMap =new ConcurrentHashMap<>();

    /**
     * 查询数据库控制器集合
     * 从数据库中可以分析出雾灯的起止地址，雾灯数量，和雾灯地址集合
     * @param wqbm 雾区编号
     * @return 控制器集合
     */
    public List<Controller> getControllers(int wqbm){
        List<Controller> controllers=controllerDAO.getControllers(wqbm);
        for(Controller controller:controllers) {
            List<LampAddress> lampAddresses=lampAddressDAO.getLampAddresses(controller.getKzqbm());
            int min=Integer.MAX_VALUE;
            int max=0;
            int wdsl=0;
            if(lampAddresses.isEmpty())
            {
                controller.setKsdz(0);
                controller.setJsdz(0);
                controller.setWdsl(0);
            }
            else
            {
                for(LampAddress lampAddress:lampAddresses)
                {
                    //分析起止地址
                    if(lampAddress.getKsdz()<min)
                    {
                        min=lampAddress.getKsdz();
                    }
                    if(lampAddress.getJsdz()>max)
                    {
                        max=lampAddress.getJsdz();
                    }


                    //控制器中会保存雾灯起止地址
                    //但是实际上并不是每个地址都有实际的灯，
                    //有可能有的只有单数的灯，也就是a灯，
                    //数据库中保存的数据可以标识出是哪类地址
                    //需要根据不同的地址计算数量
                    //对于a灯和b灯数量需要减半
                    if(lampAddress.getType()==LampAddressType.All)
                    {
                        wdsl+=lampAddress.getJsdz()-lampAddress.getKsdz()+1;
                    }
                    else if(lampAddress.getType()==LampAddressType.Odd)
                    {
                        for(int i=lampAddress.getKsdz();i<=lampAddress.getJsdz();++i)
                        {
                            if(i%2==1)
                            {
                                wdsl+=1;
                            }
                        }
                    }
                    else if(lampAddress.getType()==LampAddressType.Even)
                    {
                        for(int i=lampAddress.getKsdz();i<=lampAddress.getJsdz();++i)
                        {
                            if(i%2==0)
                            {
                                wdsl+=1;
                            }
                        }
                    }
                }
                controller.setWdsl(wdsl);
                controller.setKsdz(min);
                controller.setJsdz(max);
            }
            controller.setLampAddresses(lampAddresses);
        }

        //读取第二段地址
        for(Controller controller:controllers) {
            List<LampAddress> lampAddresses=lampAddressDAO.getLampAddresses1(controller.getKzqbm());
            int min=Integer.MAX_VALUE;
            int max=0;
            int wdsl=0;
            if(lampAddresses.isEmpty())
            {
                controller.setKsdz1(0);
                controller.setJsdz1(0);
            }
            else
            {
                for(LampAddress lampAddress:lampAddresses)
                {
                    //分析起止地址
                    if(lampAddress.getKsdz()<min)
                    {
                        min=lampAddress.getKsdz();
                    }
                    if(lampAddress.getJsdz()>max)
                    {
                        max=lampAddress.getJsdz();
                    }


                    //控制器中会保存雾灯起止地址
                    //但是实际上并不是每个地址都有实际的灯，
                    //有可能有的只有单数的灯，也就是a灯，
                    //数据库中保存的数据可以标识出是哪类地址
                    //需要根据不同的地址计算数量
                    //对于a灯和b灯数量需要减半
                    if(lampAddress.getType()==LampAddressType.All)
                    {
                        wdsl+=lampAddress.getJsdz()-lampAddress.getKsdz()+1;
                    }
                    else if(lampAddress.getType()==LampAddressType.Odd)
                    {
                        for(int i=lampAddress.getKsdz();i<=lampAddress.getJsdz();++i)
                        {
                            if(i%2==1)
                            {
                                wdsl+=1;
                            }
                        }
                    }
                    else if(lampAddress.getType()==LampAddressType.Even)
                    {
                        for(int i=lampAddress.getKsdz();i<=lampAddress.getJsdz();++i)
                        {
                            if(i%2==0)
                            {
                                wdsl+=1;
                            }
                        }
                    }
                }
                controller.setWdsl(controller.getWdsl()+wdsl);
                controller.setKsdz1(min);
                controller.setJsdz1(max);
            }
            controller.setLampAddresses1(lampAddresses);
        }

        //读取第三段地址
        for(Controller controller:controllers) {
            List<LampAddress> lampAddresses=lampAddressDAO.getLampAddresses2(controller.getKzqbm());
            int min=Integer.MAX_VALUE;
            int max=0;
            int wdsl=0;
            if(lampAddresses.isEmpty())
            {
                controller.setKsdz2(0);
                controller.setJsdz2(0);
            }
            else
            {
                for(LampAddress lampAddress:lampAddresses)
                {
                    //分析起止地址
                    if(lampAddress.getKsdz()<min)
                    {
                        min=lampAddress.getKsdz();
                    }
                    if(lampAddress.getJsdz()>max)
                    {
                        max=lampAddress.getJsdz();
                    }


                    //控制器中会保存雾灯起止地址
                    //但是实际上并不是每个地址都有实际的灯，
                    //有可能有的只有单数的灯，也就是a灯，
                    //数据库中保存的数据可以标识出是哪类地址
                    //需要根据不同的地址计算数量
                    //对于a灯和b灯数量需要减半
                    if(lampAddress.getType()==LampAddressType.All)
                    {
                        wdsl+=lampAddress.getJsdz()-lampAddress.getKsdz()+1;
                    }
                    else if(lampAddress.getType()==LampAddressType.Odd)
                    {
                        for(int i=lampAddress.getKsdz();i<=lampAddress.getJsdz();++i)
                        {
                            if(i%2==1)
                            {
                                wdsl+=1;
                            }
                        }
                    }
                    else if(lampAddress.getType()==LampAddressType.Even)
                    {
                        for(int i=lampAddress.getKsdz();i<=lampAddress.getJsdz();++i)
                        {
                            if(i%2==0)
                            {
                                wdsl+=1;
                            }
                        }
                    }
                }
                controller.setWdsl(controller.getWdsl()+wdsl);
                controller.setKsdz2(min);
                controller.setJsdz2(max);
            }
            controller.setLampAddresses2(lampAddresses);
        }

        //读取第四段地址
        for(Controller controller:controllers) {
            List<LampAddress> lampAddresses=lampAddressDAO.getLampAddresses3(controller.getKzqbm());
            int min=Integer.MAX_VALUE;
            int max=0;
            int wdsl=0;
            if(lampAddresses.isEmpty())
            {
                controller.setKsdz3(0);
                controller.setJsdz3(0);
            }
            else
            {
                for(LampAddress lampAddress:lampAddresses)
                {
                    //分析起止地址
                    if(lampAddress.getKsdz()<min)
                    {
                        min=lampAddress.getKsdz();
                    }
                    if(lampAddress.getJsdz()>max)
                    {
                        max=lampAddress.getJsdz();
                    }


                    //控制器中会保存雾灯起止地址
                    //但是实际上并不是每个地址都有实际的灯，
                    //有可能有的只有单数的灯，也就是a灯，
                    //数据库中保存的数据可以标识出是哪类地址
                    //需要根据不同的地址计算数量
                    //对于a灯和b灯数量需要减半
                    if(lampAddress.getType()==LampAddressType.All)
                    {
                        wdsl+=lampAddress.getJsdz()-lampAddress.getKsdz()+1;
                    }
                    else if(lampAddress.getType()==LampAddressType.Odd)
                    {
                        for(int i=lampAddress.getKsdz();i<=lampAddress.getJsdz();++i)
                        {
                            if(i%2==1)
                            {
                                wdsl+=1;
                            }
                        }
                    }
                    else if(lampAddress.getType()==LampAddressType.Even)
                    {
                        for(int i=lampAddress.getKsdz();i<=lampAddress.getJsdz();++i)
                        {
                            if(i%2==0)
                            {
                                wdsl+=1;
                            }
                        }
                    }
                }
                controller.setWdsl(controller.getWdsl()+wdsl);
                controller.setKsdz3(min);
                controller.setJsdz3(max);
            }
            controller.setLampAddresses3(lampAddresses);

            List<ControllerText> controllerTexts=controllerTextDAO.getControllerTexts(controller.getKzqbm());
            controller.setControllerTexts(controllerTexts);
        }
        return controllers;
    }

    /**
     * 查询数据库和缓存控制器集合
     * 从缓存中可以获取到控制器的设备状态和雾灯列表
     * @param wqbm 雾区编码，为0查询所有
     * @return 控制器集合
     */
    public List<Controller> queryControllers(int wqbm){
        List<Controller> controllers=getControllers(wqbm);
        for(Controller controller:controllers) {
            Controller cacheController = ControllerMap.get(controller.getKzqbm());
            if (cacheController == null)
            {
                controller.setErrorCount(0);
                controller.setGoodCount(0);
                controller.setSbzt(DeviceStatus.Error);
                controller.setSbztsm(codeService.getCodeValue(CodeType.Sbzt,controller.getSbzt()));
                controller.setGxsj(0L);
                controller.setWdcxzt(QueryLampResult.Error);
                controller.setWdcxztsm(codeService.getCodeValue(CodeType.Wdcx,controller.getWdcxzt()));
            }
            else
            {
                controller.setErrorCount(cacheController.getErrorCount());
                controller.setGoodCount(cacheController.getGoodCount());
                controller.setSbzt(cacheController.getSbzt());
                controller.setSbztsm(cacheController.getSbztsm());
                controller.setGxsj(cacheController.getGxsj());
                controller.setWdcxzt(cacheController.getWdcxzt());
                controller.setWdcxztsm(cacheController.getWdcxztsm());
            }
        }
        Collections.sort(controllers, Comparator.comparingInt(Controller::getKzqbsm));
        return controllers;
    }

    /**
     * 主要用于从缓存中获取控制器的雾灯集合
     * @param kzqbm 控制器编码
     * @return 控制器缓存
     */
    public Controller getControllerCache(int kzqbm){
        Controller controllerCache= ControllerMap.get(kzqbm);
        if(controllerCache!=null&&controllerCache.getLamps()!=null)
        {
            String id=String.format("%d_%d",controllerCache.getKzqdk(),controllerCache.getKzqbsm()  );
            if(LampMap.containsKey(id))
            {
                for(Lamp lamp: controllerCache.getLamps())
                {
                    if(LampMap.get(id).containsKey(lamp.getWdbm()))
                    {
                        lamp.setHasCrash(LampMap.get(id).get(lamp.getWdbm()));
                    }
                }
            }
        }
        return controllerCache;
    }

    public void updateLampCache(Lamp lamp)
    {
        String id=String.format("%d_%d",lamp.getKzqdk(),lamp.getKzqbsm());
        if(!LampMap.containsKey(id))
        {
            LampMap.put(id,new HashMap<>());
        }
        lamp.setHasCrashsm(codeService.getCodeValue(CodeType.Sbzt, lamp.getHasCrash()+1));
        LampMap.get(id).put(lamp.getWdbm(),lamp.getHasCrash());
    }

    /**
     * 添加控制器
     * @param controller 控制器
     * @return 添加后的主键
     */
    @Transactional
    public void insertController(Controller controller)
    {
        if(controller.getVersion()==null)
        {
            controller.setVersion("2022/03/18");
        }
        controllerDAO.insertController(controller);
        if(controller.getControllerTexts()!=null)
        {
            for(ControllerText controllerText :controller.getControllerTexts())
            {
                controllerText.setKzqbm(controller.getKzqbm());
                controllerTextDAO.insertControllerText(controllerText);
            }
        }
        if(controller.getLampAddresses()!=null)
        {
            for(LampAddress lampAddress:controller.getLampAddresses())
            {
                lampAddress.setKzqbm(controller.getKzqbm());
                lampAddressDAO.insertLampAddress(lampAddress);
            }
        }

        if(controller.getLampAddresses1()!=null)
        {
            for(LampAddress lampAddress:controller.getLampAddresses1())
            {
                lampAddress.setKzqbm(controller.getKzqbm());
                lampAddressDAO.insertLampAddress1(lampAddress);
            }
        }
        if(controller.getLampAddresses2()!=null)
        {
            for(LampAddress lampAddress:controller.getLampAddresses2())
            {
                lampAddress.setKzqbm(controller.getKzqbm());
                lampAddressDAO.insertLampAddress2(lampAddress);
            }
        }
        if(controller.getLampAddresses3()!=null)
        {
            for(LampAddress lampAddress:controller.getLampAddresses3())
            {
                lampAddress.setKzqbm(controller.getKzqbm());
                lampAddressDAO.insertLampAddress3(lampAddress);
            }
        }
    }

    /**
     * 更新控制器
     * @param controller 控制器
     */
    @Transactional
    public void updateController(Controller controller)
    {
        if(controller.getVersion()==null)
        {
            controller.setVersion("2022/03/18");
        }
        controllerDAO.updateController(controller);

        controllerTextDAO.deleteControllerText(controller.getKzqbm());
        if(controller.getControllerTexts()!=null)
        {
            for (ControllerText text:controller.getControllerTexts())
            {
                text.setKzqbm(controller.getKzqbm());
                controllerTextDAO.insertControllerText(text);
            }
        }


        lampAddressDAO.deleteLampAddresses(controller.getKzqbm());
        lampAddressDAO.deleteLampAddresses1(controller.getKzqbm());
        lampAddressDAO.deleteLampAddresses2(controller.getKzqbm());
        lampAddressDAO.deleteLampAddresses3(controller.getKzqbm());
        if(controller.getLampAddresses()!=null)
        {
            for(LampAddress lampAddress:controller.getLampAddresses())
            {
                lampAddress.setKzqbm(controller.getKzqbm());
                lampAddressDAO.insertLampAddress(lampAddress);
            }
        }
        if(controller.getLampAddresses1()!=null)
        {
            for(LampAddress lampAddress:controller.getLampAddresses1())
            {
                lampAddress.setKzqbm(controller.getKzqbm());
                lampAddressDAO.insertLampAddress1(lampAddress);
            }
        }
        if(controller.getLampAddresses2()!=null)
        {
            for(LampAddress lampAddress:controller.getLampAddresses2())
            {
                lampAddress.setKzqbm(controller.getKzqbm());
                lampAddressDAO.insertLampAddress2(lampAddress);
            }
        }
        if(controller.getLampAddresses3()!=null)
        {
            for(LampAddress lampAddress:controller.getLampAddresses3())
            {
                lampAddress.setKzqbm(controller.getKzqbm());
                lampAddressDAO.insertLampAddress3(lampAddress);
            }
        }
    }

    /**
     * 删除控制器
     * @param kzqbm 控制器编码
     */
    @Transactional
    public void deleteController(int kzqbm)
    {
        controllerDAO.deleteController(kzqbm);
        controllerTextDAO.deleteControllerText(kzqbm);
        lampAddressDAO.deleteLampAddresses(kzqbm);
        lampAddressDAO.deleteLampAddresses1(kzqbm);
        lampAddressDAO.deleteLampAddresses2(kzqbm);
        lampAddressDAO.deleteLampAddresses3(kzqbm);
    }

    private void setLampController(Lamp lamp,Controller controller)
    {
        lamp.setKzqbm(controller.getKzqbm());
        lamp.setKzqmc(controller.getKzqmc());
        lamp.setWqbm(controller.getWqbm());
        lamp.setWqmc(controller.getWqmc());
    }
    private void setErrorLamp(Lamp lamp)
    {
        lamp.setWdljzt(LampStatus.Disconnection);
        lamp.setMzt(LampDoorStatus.Steal);
        lamp.setWdzt(LampTemperatureStatus.TooHigh);
        lamp.setDyzt(LampVoltageStatus.TooLow);
        lamp.setSbpd(LampPairStatus.Disconnection);
        lamp.setLedzt(LampLedStatus.Close);
        lamp.setLdzt(LampRadarStatus.Close);
        lamp.setWdwd(0);
        lamp.setXdcdy(0);
        lamp.setTyndy(0);
        lamp.setSbzt(DeviceStatus.Error);
    }

    private void setLampCode(Lamp lamp)
    {
        lamp.setWdljztsm(codeService.getCodeValue(CodeType.Wdljzt,lamp.getWdljzt()));
        lamp.setSbztsm(codeService.getCodeValue(CodeType.Sbzt,lamp.getSbzt()));

        if(lamp.getWdljzt()==LampStatus.Disconnection)
        {
            lamp.setMztsm("-");
            lamp.setWdztsm("-");
            lamp.setDyztsm("-");
            lamp.setDdyztsm("-");
            lamp.setSbpdsm("-");
            lamp.setLedztsm("-");
            lamp.setLdztsm("-");
        }
        else
        {
            lamp.setMztsm(codeService.getCodeValue(CodeType.Mzt,lamp.getMzt()));
            lamp.setWdztsm(codeService.getCodeValue(CodeType.Wdzt,lamp.getWdzt()));
            lamp.setDyztsm(codeService.getCodeValue(CodeType.Dyzt,lamp.getDyzt()));
            lamp.setDdyztsm(codeService.getCodeValue(CodeType.Dyzt,lamp.getDdyzt()));
            lamp.setSbpdsm(codeService.getCodeValue(CodeType.Sbpd,lamp.getSbpd()));
            lamp.setLedztsm(codeService.getCodeValue(CodeType.Ledzt,lamp.getLedzt()));
            lamp.setLdztsm(codeService.getCodeValue(CodeType.Ldzt,lamp.getLdzt()));
        }

    }

    /**
     * 查询单个雾灯状态
     * @param kzqbm 控制器编码
     * @param kzqbsm 控制器标识码
     * @param wdbm 雾灯编码
     */
    public Lamp queryLamp(int kzqbm,int dk,int kzqbsm,int wdbm) throws IOException {

        QueryLampStatus queryLampStatus=new QueryLampStatus();
        byte[] buffer = queryLampStatus.toBuffer(kzqbsm,wdbm);
        SocketResult result= sendShoot(dk,kzqbsm, buffer,queryLampStatus.getId(),null);
        if(result.getResult() ==SendResult.Success)
        {
            Lamp lamp=queryLampStatus.toModel(result.getReceive());
            lamp.setKzqdk(dk);
            setLampCode(lamp);

            //更新缓存
            Controller controller=ControllerMap.get(kzqbm);
            if(controller!=null)
            {
                List<Lamp> lamps=controller.getLamps();
                for(int i=0;i<controller.getLamps().size();++i)
                {
                    Lamp oldLamp=lamps.get(i);
                    if(oldLamp.getWdbm()==lamp.getWdbm())
                    {
                        oldLamp.setXdcdy(lamp.getXdcdy());
                        oldLamp.setTyndy(lamp.getTyndy());
                        oldLamp.setWdwd(lamp.getWdwd());

                        oldLamp.setWdljzt(LampStatus.Normal);
                        oldLamp.setMzt(lamp.getMzt());
                        oldLamp.setWdzt(lamp.getWdzt());
                        oldLamp.setDyzt(lamp.getDyzt());
                        oldLamp.setSbpd(lamp.getSbpd());
                        oldLamp.setLedzt(lamp.getLedzt());
                        oldLamp.setLdzt(lamp.getLdzt());
                        oldLamp.setDdyzt(lamp.getDdyzt());
                        oldLamp.setSbzt(lamp.getSbzt());

                        oldLamp.setWdljztsm(lamp.getWdljztsm());
                        oldLamp.setMztsm(lamp.getMztsm());
                        oldLamp.setWdztsm(lamp.getWdztsm());
                        oldLamp.setDyztsm(lamp.getDyztsm());
                        oldLamp.setSbpdsm(lamp.getSbpdsm());
                        oldLamp.setLedztsm(lamp.getLedztsm());
                        oldLamp.setLdztsm(lamp.getLdztsm());
                        oldLamp.setDdyztsm(lamp.getDdyztsm());
                        oldLamp.setSbztsm(lamp.getSbztsm());
                        break;
                    }
                }
            }
            return lamp;
        }
        else
        {
            return null;
        }
    }

    /**
     * 从设备中获取所有控制器的雾灯集合
     * 会在task中调用，是更新控制器状态和雾灯列表的唯一途径
     * @throws IOException
     */
    public void queryLampCaches(int timeout){


        for(FogArea fogArea: fogAreaDAO.getFogAreas(Department.AllTag))
        {
            try
            {
//                if(fogArea.getWqbm()!=108)
//                {
//                    continue;
//                }
                String joinId=UUID.randomUUID().toString();
                StringBuilder contentBuilder=new StringBuilder();
                Date start=new Date();
                contentBuilder.append(String.format("%s:\n",fogArea.getWqmc()));
                boolean hasError=false;
                for(Controller controller:getControllers(fogArea.getWqbm()))
                {
                    //这个变量保存了所有雾灯的编码
                    //对于实际上没有的灯，比如a灯之后紧跟的偶数编号不能保存进来
                    Set<Integer> lampSet=new HashSet<>();
                    //第一段
                    List<LampAddress> lampAddresses=controller.getLampAddresses();
                    for(LampAddress lampAddress:lampAddresses)
                    {
                        if(lampAddress.getType()==LampAddressType.All)
                        {
                            for(int i=lampAddress.getKsdz();i<=lampAddress.getJsdz();++i)
                            {
                                lampSet.add(i);
                            }
                        }
                        else if(lampAddress.getType()==LampAddressType.Odd)
                        {
                            for(int i=lampAddress.getKsdz();i<=lampAddress.getJsdz();++i)
                            {
                                if(i%2==1)
                                {
                                    lampSet.add(i);
                                }
                            }
                        }
                        else if(lampAddress.getType()==LampAddressType.Even)
                        {
                            for(int i=lampAddress.getKsdz();i<=lampAddress.getJsdz();++i)
                            {
                                if(i%2==0)
                                {
                                    lampSet.add(i);
                                }
                            }
                        }
                    }

                    //第二段
                    List<LampAddress> lampAddresses1=controller.getLampAddresses1();
                    for(LampAddress lampAddress1:lampAddresses1)
                    {
                        if(lampAddress1.getType()==LampAddressType.All)
                        {
                            for(int i=lampAddress1.getKsdz();i<=lampAddress1.getJsdz();++i)
                            {
                                lampSet.add(i);
                            }
                        }
                        else if(lampAddress1.getType()==LampAddressType.Odd)
                        {
                            for(int i=lampAddress1.getKsdz();i<=lampAddress1.getJsdz();++i)
                            {
                                if(i%2==1)
                                {
                                    lampSet.add(i);
                                }
                            }
                        }
                        else if(lampAddress1.getType()==LampAddressType.Even)
                        {
                            for(int i=lampAddress1.getKsdz();i<=lampAddress1.getJsdz();++i)
                            {
                                if(i%2==0)
                                {
                                    lampSet.add(i);
                                }
                            }
                        }
                    }
                    //第三段
                    List<LampAddress> lampAddresses2=controller.getLampAddresses2();
                    for(LampAddress lampAddress2:lampAddresses2)
                    {
                        if(lampAddress2.getType()==LampAddressType.All)
                        {
                            for(int i=lampAddress2.getKsdz();i<=lampAddress2.getJsdz();++i)
                            {
                                lampSet.add(i);
                            }
                        }
                        else if(lampAddress2.getType()==LampAddressType.Odd)
                        {
                            for(int i=lampAddress2.getKsdz();i<=lampAddress2.getJsdz();++i)
                            {
                                if(i%2==1)
                                {
                                    lampSet.add(i);
                                }
                            }
                        }
                        else if(lampAddress2.getType()==LampAddressType.Even)
                        {
                            for(int i=lampAddress2.getKsdz();i<=lampAddress2.getJsdz();++i)
                            {
                                if(i%2==0)
                                {
                                    lampSet.add(i);
                                }
                            }
                        }
                    }
                    //第四段
                    List<LampAddress> lampAddresses3=controller.getLampAddresses3();
                    for(LampAddress lampAddress3:lampAddresses3)
                    {
                        if(lampAddress3.getType()==LampAddressType.All)
                        {
                            for(int i=lampAddress3.getKsdz();i<=lampAddress3.getJsdz();++i)
                            {
                                lampSet.add(i);
                            }
                        }
                        else if(lampAddress3.getType()==LampAddressType.Odd)
                        {
                            for(int i=lampAddress3.getKsdz();i<=lampAddress3.getJsdz();++i)
                            {
                                if(i%2==1)
                                {
                                    lampSet.add(i);
                                }
                            }
                        }
                        else if(lampAddress3.getType()==LampAddressType.Even)
                        {
                            for(int i=lampAddress3.getKsdz();i<=lampAddress3.getJsdz();++i)
                            {
                                if(i%2==0)
                                {
                                    lampSet.add(i);
                                }
                            }
                        }
                    }
                    contentBuilder.append(String.format("controller %d:",controller.getKzqbsm()));

                    //查询雾灯
                    Map<Integer,Lamp> lampMap=queryLamps(controller.getKzqdk(),controller.getKzqbsm(),controller.getKsdz(),controller.getJsdz(),joinId);
                    if(controller.getKsdz1()!=0)
                    {
                        Map<Integer,Lamp> lampMap1=queryLamps(controller.getKzqdk(),controller.getKzqbsm(),controller.getKsdz1(),controller.getJsdz1(),joinId);
                        if(lampMap1!=null)
                        {
                            lampMap.putAll(lampMap1);
                        }

                    }
                    if(controller.getKsdz2()!=0)
                    {
                        Map<Integer,Lamp> lampMap2=queryLamps(controller.getKzqdk(),controller.getKzqbsm(),controller.getKsdz2(),controller.getJsdz2(),joinId);
                        if(lampMap2!=null)
                        {
                            lampMap.putAll(lampMap2);
                        }
                    }
                    if(controller.getKsdz3()!=0)
                    {
                        Map<Integer,Lamp> lampMap3=queryLamps(controller.getKzqdk(),controller.getKzqbsm(),controller.getKsdz3(),controller.getJsdz3(),joinId);
                        if(lampMap3!=null)
                        {
                            lampMap.putAll(lampMap3);
                        }
                    }

                    List<Lamp> lamps=new ArrayList<>();

                    if (lampMap == null) {
                        //控制器连接失败，用故障灯填充列表
                        for(Integer wdbm:lampSet) {
                            Lamp lamp=new Lamp();
                            lamp.setWdbm(wdbm);

                            setLampController(lamp,controller);
                            setErrorLamp(lamp);
                            setLampCode(lamp);

                            lamps.add(lamp);
                        }
                        controller.setWdcxzt(QueryLampResult.Error);
                        controller.setWdcxztsm(codeService.getCodeValue(CodeType.Wdcx,controller.getWdcxzt()));
                        controller.setErrorCount(lamps.size());
                        controller.setGoodCount(0);
                        controller.setSbzt(DeviceStatus.Error);
                        controller.setSbztsm(codeService.getCodeValue(CodeType.Sbzt,controller.getSbzt()));
                        contentBuilder.append(String.format("控制器失联 %d\n",controller.getErrorCount()));
                        hasError=true;
                    }
                    else if(lampMap.isEmpty())
                    {
                        //如果查询出来的雾灯列表为空
                        //表示可以连上控制器，但是控制器也没有获取到状态
                        //所以需要把控制器状态设置为正常，雾灯列表设置为异常
                        for(Integer wdbm:lampSet) {
                            Lamp lamp=new Lamp();
                            lamp.setWdbm(wdbm);
                            setLampController(lamp,controller);
                            setErrorLamp(lamp);
                            setLampCode(lamp);

                            lamps.add(lamp);
                        }
                        controller.setWdcxzt(QueryLampResult.Empty);
                        controller.setWdcxztsm(codeService.getCodeValue(CodeType.Wdcx,controller.getWdcxzt()));
                        controller.setErrorCount(lamps.size());
                        controller.setGoodCount(0);
                        controller.setSbzt(DeviceStatus.Noraml);
                        controller.setSbztsm(codeService.getCodeValue(CodeType.Sbzt,controller.getSbzt()));
                        contentBuilder.append(String.format("未能从控制器中获取雾灯状态 error %d\n",controller.getErrorCount()));
                        hasError=true;
//因为如果获取雾灯状态为空，很有可能是没有设置开始和结束地址，但是后来现场不让随意下发03协议所以注释
//                    SocketResult result=setController(controller,joinId);
//                    contentBuilder.append(String.format("设置控制器基本参数 %s\n",result));
                    }
                    else
                    {
                        //查询成功分析每一个雾灯的数据
                        int good=0;
                        int error=0;
                        for(Integer wdbm:lampSet)
                        {
                            if(lampMap.containsKey(wdbm))
                            {
                                Lamp lamp=lampMap.get(wdbm);
                                lamp.setWdbm(wdbm);
                                setLampController(lamp,controller);
                                setLampCode(lamp);

                                lamps.add(lamp);
                                if(lamp.getSbzt()==DeviceStatus.Noraml)
                                {
                                    ++good;
                                }
                                else
                                {
                                    ++error;
                                }
                            }
                            else
                            {
                                Lamp lamp=new Lamp();
                                lamp.setWdbm(wdbm);
                                setLampController(lamp,controller);
                                setErrorLamp(lamp);
                                setLampCode(lamp);
                                lamps.add(lamp);
                                ++error;
                            }
                        }

                        controller.setWdcxzt(QueryLampResult.Success);
                        controller.setWdcxztsm(codeService.getCodeValue(CodeType.Wdcx,controller.getWdcxzt()));
                        controller.setSbzt(DeviceStatus.Noraml);
                        controller.setSbztsm(codeService.getCodeValue(CodeType.Sbzt,DeviceStatus.Noraml));
                        controller.setGoodCount(good);
                        controller.setErrorCount(error);
                        contentBuilder.append(String.format("正常雾灯 %d 异常雾灯 %d\n",controller.getGoodCount(),controller.getErrorCount()));

                    }

                    //根据故障在前，正常在后，随后按照编号排序
                    Collections.sort(lamps, (l1, l2) -> {
                        if(l1.getSbzt()==l2.getSbzt())
                        {
                            return l1.getWdbm()-l2.getWdbm();
                        }
                        else
                        {
                            return l2.getSbzt()-l1.getSbzt();
                        }
                    });
                    controller.setGxsj(new Date().getTime());
                    controller.setLamps(lamps);
                    //更新缓存
                    ControllerMap.put(controller.getKzqbm(),controller);
                }

                int testCount;
                if(hasError)
                {
                    Integer temp = TestMap.get(fogArea.getWqbm());
                    testCount=temp==null?1:temp+1;
                }
                else
                {
                    testCount=0;
                }

                //如果超过指定的测试次数则切换到备用控制器
                if (timeout>0&&testCount >= timeout) {
                    SocketResult<Integer> sr1 = queryRelayStatus(fogArea.getJdqbsm(),joinId);


                    SocketResult sr2;
                    if (sr1.getData() == RelayControlMode.Main) {
                        sr2 = setRelayBak(fogArea,joinId);
                    }
                    else if(sr1.getData()==RelayControlMode.Bak)
                    {
                        sr2 = setRelayMain(fogArea,joinId);
                    }
                    else
                    {
                        sr2=new SocketResult();
                        sr2.setResult(SendResult.Disconnection);
                    }
                    contentBuilder.append(String.format("relay %d %s\n", sr1.getData(), sr2.getResult()));
                    testCount=0;
                }

                //更新缓存
                TestMap.put(fogArea.getWqbm(), testCount);

                Date end=new Date();
                contentBuilder.append(String.format("耗时:%.3fs",(end.getTime()-start.getTime())/1000.0));
                logService.insertSystemLog(Token.SystemToken, SystemLogType.QueryLamps,contentBuilder.toString(),joinId);
            }
            catch (Exception ex)
            {
                logService.insertExceptionLog(ex);
            }
        }

    }

    /**
     * 获取控制器的能见度等级集合
     * 填充字典描述字段
     * @param token token
     * @param kzqbsm 控制器标识码
     * @return 能见度等级集合
     * @throws IOException
     */
    public List<VisibilityScale> queryVisibilityScales(String token, int dk,int kzqbsm) throws IOException {

        SocketResult<List<VisibilityScale>> visibilityScales=queryVisibilityScale(dk,kzqbsm);
        if(visibilityScales.getData()!=null)
        {
            for(VisibilityScale visibilityScale:visibilityScales.getData())
            {
                visibilityScale.setWdkzsm(codeService.getCodeValue(CodeType.Wdkz,visibilityScale.getWdkz()));
            }
        }
        return visibilityScales.getData();
    }

    /** * 发送字节流
     * @param kzqbsm 控制器标识码
     * @param buffer 发送字节流
     * @param joinId 日志关联编号
     * @return 发送结果
     */
    private SendResult sendShoot1(int dk,int kzqbsm, byte[] buffer,int protocolId,String joinId) throws IOException {
        if(SocketTask.ProtocolHandler==null)
        {
            return SendResult.Disconnection;
        }
        else
        {
            Shoot shoot=new Shoot();
            byte[] sendBuffer=shoot.request(dk,kzqbsm, buffer, protocolId);
            SendResult result=SocketTask.ProtocolHandler.sendTcp(sendBuffer);
            logService.insertSocketLog(protocolId,kzqbsm,dk, Convert.toHex(buffer),result.ordinal(),null,joinId);
            return result;
        }
    }

    /** * 发送字节流
     * @param kzqbsm 控制器标识码
     * @param buffer 发送字节流
     * @param protocolId 等待协议编号
     * @param joinId 日志关联编号
     * @return 发送结果
     */
    private SocketResult sendShoot(int kzqbsm, byte[] buffer, int protocolId,String joinId) throws IOException {
        SocketResult sr=new SocketResult();
        sr.setResult(SendResult.Disconnection);
        return sr;
//        if(SocketTask.ProtocolHandler==null)
//        {
//            SocketResult sr=new SocketResult();
//            sr.setResult(SendResult.Disconnection);
//            return sr;
//        }
//        else
//        {
//            Shoot shoot=new Shoot();
//            byte[] sendBuffer=shoot.request(0,kzqbsm, buffer, protocolId);
//            SocketResult sr=SocketTask.ProtocolHandler.sendTcp(shoot.getId()+1,shoot.getStampTime(),sendBuffer);
//            sr=shoot.handle(sr);
//            logService.insertSocketLog(protocolId,kzqbsm,0, Convert.toHex(buffer),sr.getResult().ordinal(),Convert.toHex(sr.getReceive()),joinId);
//            return sr;
//        }
    }

    /** * 发送字节流
     * @param kzqbsm 控制器标识码
     * @param buffer 发送字节流
     * @param protocolId 等待协议编号
     * @param joinId 日志关联编号
     * @return 发送结果
     */
    public SocketResult sendShoot(int dk,int kzqbsm, byte[] buffer, int protocolId,String joinId) throws IOException {
        if(SocketTask.ProtocolHandler==null)
        {
            SocketResult sr=new SocketResult();
            sr.setResult(SendResult.Disconnection);
            return sr;
        }
        else
        {
            Shoot shoot=new Shoot();
            byte[] sendBuffer=shoot.request(dk,kzqbsm, buffer, protocolId);
            SocketResult sr=SocketTask.ProtocolHandler.sendTcp(shoot.getId()+1,shoot.getStampTime(),dk,kzqbsm,protocolId,sendBuffer);
            sr=shoot.handle(sr);
            logService.insertSocketLog(protocolId,kzqbsm,dk, Convert.toHex(buffer),sr.getResult().ordinal(),Convert.toHex(sr.getReceive()),joinId);
            return sr;
        }
    }

    /**
     * 重启控制器
     * @param kzqbsm 控制器标识码
     * @param joinId 关联编号
     * @return 发送结果
     * @throws IOException
     */
    public SocketResult restartController(int dk,int kzqbsm,String joinId) throws IOException {

        //重启雾灯
        SetLampRestart lampRestart=new SetLampRestart();
        byte[] buffer = lampRestart.toBuffer(kzqbsm);
        SocketResult sr=sendShoot(dk,kzqbsm, buffer,lampRestart.getId(),joinId);
        if(sr.getResult()!=SendResult.Success)
        {
            return sr;
        }
        //重启控制
        SetControllerRestart controlRestart=new SetControllerRestart();
        buffer = controlRestart.toBuffer(kzqbsm);
        return sendShoot(dk,kzqbsm, buffer,controlRestart.getId(),joinId);
    }

    /**
     * 查询控制器太阳能信息
     * @param controller 控制器
     * @return 发送结果
     * @throws IOException
     */
    public SendResult querySolarEnergy(Controller controller,StringBuilder builder,String joinId) throws IOException {
        if(controller.getVersion().compareTo("2021/09/04")<0)
        {
            if(builder!=null) {

                builder.append(String.format("查询太阳能参数->%s 不支持查询太阳能参数 版本:%s",controller.getKzqmc(),controller.getVersion()));
            }
            controller.setHasSolarEnergyData(false);
            controller.setDcqygj(false);
            controller.setDcdl(0);
            controller.setDcdy("-");
            controller.setTyndy("-");
            controller.setCddl("-");
            return SendResult.Success;
        }
        QuerySolarEnergy querySolarEnergy=new QuerySolarEnergy();
        byte[] buffer = querySolarEnergy.toBuffer(controller.getKzqbsm());
        Date d1=new Date();
        SocketResult result= sendShoot(controller.getKzqdk(),controller.getKzqbsm(), buffer,querySolarEnergy.getId(),joinId);
        Date d2=new Date();

        if(result.getResult() ==SendResult.Success)
        {
            Controller model=querySolarEnergy.toModel(result.getReceive());
            controller.setHasSolarEnergyData(model.isHasSolarEnergyData());
            controller.setDcqygj(model.isDcqygj());
            controller.setDcdl(model.getDcdl());
            controller.setDcdy(model.getDcdy());
            controller.setTyndy(model.getTyndy());
            controller.setCddl(model.getCddl());
        }
        else
        {
            controller.setHasSolarEnergyData(false);
            controller.setDcqygj(false);
            controller.setDcdl(0);
            controller.setDcdy("-");
            controller.setTyndy("-");
            controller.setCddl("-");
        }
        if(builder!=null)
        {
            builder.append(String.format("查询太阳能参数->%s 结果:%s 太阳能信息查询状态:%b 电池欠压警告:%b 电池电量:%d 电池电压:%s 太阳能电压:%s 充电电流:%s 耗时:%d\n"
                    ,controller.getKzqmc(), result.getResult(), controller.isHasSolarEnergyData(), controller.isDcqygj(), controller.getDcdl(), controller.getDcdy(), controller.getTyndy(), controller.getCddl(),d2.getTime()-d1.getTime()));
        }
        return result.getResult();
    }

    /**
     * 设置控制器运行参数
     * @param controller 控制器
     * @param joinId 关联编号
     * @return 发送结果
     * @throws IOException
     */
    public SendResult setControllerConfig(Controller controller,StringBuilder builder,String joinId) throws IOException {
        SetControllerConfig setControllerConfig=new SetControllerConfig();
        byte[] buffer = setControllerConfig.toBuffer(controller.getKzqbsm(),controller);
        Date d1=new Date();
        SendResult result= sendShoot(controller.getKzqdk(),controller.getKzqbsm(), buffer,setControllerConfig.getId(),joinId).getResult();
        Date d2=new Date();

        if(builder!=null)
        {
            builder.append(String.format("设置运行参数->%s 结果:%s 雾灯状态:%d 雾灯亮度:%d 亮灯时长:%d 灭灯时长:%d 红灯延时:%d 盲区延时:%d 红色警示灯数量:%d 耗时:%d\n"
                    ,controller.getKzqmc(),result, controller.getWdkz(),controller.getWdld(), controller.getLdsc(), controller.getMdsc()
                    , controller.getHdys(), controller.getMqys(), controller.getHsjsdzsl(),d2.getTime()-d1.getTime()));
        }
        return result;
    }
    public Tuple<Integer,Integer> queryControllerText(Controller controller,boolean onlyManual,StringBuilder builder,String joinId) throws IOException {

        if(!controller.isZcwz())
        {
            if(builder!=null)
            {
                builder.append(String.format("查询文字列表->%s 不支持文字功能\n",controller.getKzqmc()));
            }

            List<ControllerText> controllerTexts =new ArrayList<>();
            controller.setControllerTexts(controllerTexts);
            return new Tuple<>(0,0);
        }
        if(builder!=null)
        {
            builder.append(String.format("查询文字列表->%s\n",controller.getKzqmc()));
        }
        QueryControllerText queryControllerText =new QueryControllerText();
        List<ControllerText> controllerTexts =new ArrayList<>();
        controller.setControllerTexts(controllerTexts);
        int goodCount=0;
        int errorCount=0;
        for(int i=0;i<=17;++i)
        {
            if(onlyManual&&i>0)
            {
                break;
            }
            byte[] buffer= queryControllerText.toBuffer(controller.getKzqbsm(),i);
            Date d1=new Date();
            SocketResult<ControllerText> result= sendShoot(controller.getKzqdk(),controller.getKzqbsm(), buffer, queryControllerText.getId(),joinId);
            Date d2=new Date();

            if(result.getResult() ==SendResult.Success)
            {
                goodCount+=1;
                ControllerText model=queryControllerText.toModel(result.getReceive());
                controllerTexts.add(model);
                if(builder!=null) {
                    builder.append(String.format("编号:%d 文字:%s 耗时:%d\n", model.getLxbh(), model.getWdwz(),d2.getTime()-d1.getTime()));
                }
            }
            else
            {
                errorCount+=1;
                ControllerText controllerText =new ControllerText();
                controllerText.setLxbh(i);
                controllerText.setWdwz("");
                controllerTexts.add(controllerText);
                if(builder!=null) {
                    builder.append(String.format("编号:%d 失败\n", i));
                }
            }
        }
        return new Tuple<>(goodCount,errorCount);
    }

    public Tuple<Integer,Integer> setControllerText(Controller controller, boolean onlyManual, StringBuilder builder, String joinId) throws IOException {

        boolean needLog=false;
        if(builder==null)
        {
            needLog=true;
            joinId=UUID.randomUUID().toString();
            builder = new StringBuilder();
        }

        if(!controller.isZcwz())
        {
            builder.append(String.format("设置文字列表->%s 不支持文字功能\n",controller.getKzqmc()));
            if(needLog)
            {
                logService.insertSystemLog(Token.SystemToken, SystemLogType.SetControllerTextList,builder.toString(),joinId);
            }
            return new Tuple<>(0,0);
        }
        builder.append(String.format("设置文字列表->%s\n",controller.getKzqmc()));

        SetControllerText setControllerText=new SetControllerText();
        int goodCount=0;
        int errorCount=0;
        for(ControllerText text:controller.getControllerTexts())
        {
            if(onlyManual&&text.getLxbh()!=0)
            {
                continue;
            }
            if(!onlyManual&&text.getLxbh()==0)
            {
                continue;
            }

            byte[] buffer = setControllerText.toBuffer(controller.getKzqbsm(),text);
            Date d1=new Date();
            SocketResult result= sendShoot(controller.getKzqdk(),controller.getKzqbsm(), buffer,setControllerText.getId(),joinId);
            Date d2=new Date();
            if(result.getResult()==SendResult.Success)
            {
                goodCount+=1;
            }
            else
            {
                errorCount+=1;
            }
            builder.append(String.format("编号:%d 文字:%s 结果:%s 耗时:%d\n",text.getLxbh(),text.getWdwz(),result.getResult(),d2.getTime()-d1.getTime()));
        }
        if(needLog)
        {
            logService.insertSystemLog(Token.SystemToken, SystemLogType.SetControllerTextList,builder.toString(),joinId);
        }
        return new Tuple<>(goodCount,errorCount);
    }
    public SendResult queryControllerTextConfig(Controller controller,StringBuilder builder,String joinId) throws IOException {
        if(!controller.isZcwz())
        {
            if(builder!=null)
            {
                builder.append(String.format("查询文字参数->%s 不支持文字功能\n",controller.getKzqmc()));
            }
            controller.setLxbh(-1);

            controller.setCfsd(0);
            controller.setDscf(0);
            controller.setQxcf(0);
            controller.setSfgs(0);
            controller.setWzmk2(0);
            controller.setWzmk1(0);
            controller.setWdgz(0);

            controller.setGs_Lddj(0);
            controller.setGs_Sspl(0);
            controller.setGs_Zkb(0);
            return SendResult.Success;
        }
        QueryControllerTextConfig queryControllerTextConfig =new QueryControllerTextConfig();
        byte[] buffer= queryControllerTextConfig.toBuffer(controller.getKzqbsm());
        Date d1=new Date();
        SocketResult result= sendShoot(controller.getKzqdk(),controller.getKzqbsm(), buffer, queryControllerTextConfig.getId(),joinId);
        Date d2=new Date();
        if(result.getResult()==SendResult.Success)
        {
            Controller model= queryControllerTextConfig.toModel(result.getReceive());

            controller.setLxbh(model.getLxbh());

            controller.setCfsd(model.getCfsd());
            controller.setSfgs(model.getSfgs());
            controller.setDscf(model.getDscf());
            controller.setQxcf(model.getQxcf());
            controller.setWzmk2(model.getWzmk2());
            controller.setWzmk1(model.getWzmk1());
            controller.setWdgz(model.getWdgz());

            controller.setGs_Lddj(model.getGs_Lddj());
            controller.setGs_Sspl(model.getGs_Sspl());
            controller.setGs_Zkb(model.getGs_Zkb());
        }
        else
        {
            controller.setLxbh(-1);

            controller.setCfsd(0);
            controller.setSfgs(0);
            controller.setDscf(0);
            controller.setQxcf(0);
            controller.setWzmk2(0);
            controller.setWzmk1(0);
            controller.setWdgz(0);

            controller.setGs_Lddj(0);
            controller.setGs_Sspl(0);
            controller.setGs_Zkb(0);

        }

        if(builder!=null)
        {
            builder.append(String.format("查询文字参数->%s 结果:%s 持续手动:%d 是否跟随:%d 定时触发:%d 气象触发:%d 文字模块2:%d 文字模块1:%d 雾灯工作:%d 亮度等级:%d 闪烁频率:%d 占空比:%d 类型编号%d 耗时:%d\n"
                    ,controller.getKzqmc(),result.getResult()
                    ,controller.getCfsd(),controller.getSfgs(),controller.getDscf(),controller.getQxcf(),controller.getWzmk2(),controller.getWzmk1(),controller.getWdgz()
                    ,controller.getGs_Lddj(),controller.getGs_Sspl(),controller.getGs_Zkb(),controller.getLxbh(),d2.getTime()-d1.getTime()));
        }
        return result.getResult();
    }

    public SendResult setControllerTextConfig(Controller controller,StringBuilder builder,String joinId) throws IOException {
        if(!controller.isZcwz())
        {
            if(builder!=null)
            {
                builder.append(String.format("设置文字参数->%s 不支持文字功能\n",controller.getKzqmc()));
            }
            return SendResult.Success;
        }

        SetControllerTextConfig setControllerTextConfig=new SetControllerTextConfig();
        byte[] buffer = setControllerTextConfig.toBuffer(controller.getKzqbsm(),controller);
        Date d1=new Date();
        SendResult result= sendShoot(controller.getKzqdk(),controller.getKzqbsm(), buffer,setControllerTextConfig.getId(),joinId).getResult();
        Date d2=new Date();
        if(buffer!=null)
        {
            builder.append(String.format("设置文字参数->%s 结果:%s 触发手动:%d 是否跟随:%d 定时触发:%d 气象触发:%d 文字模块2:%d 文字模块1:%d 雾灯工作:%d 亮度等级:%d 闪烁频率:%d 占空比:%d 耗时:%d\n"
                    ,controller.getKzqmc(), result,controller.getCfsd(),controller.getSfgs(),controller.getDscf(),controller.getQxcf(),controller.getWzmk2(),controller.getWzmk1(),controller.getWdgz(),controller.getGs_Lddj(),controller.getGs_Sspl(),controller.getGs_Zkb(),d2.getTime()-d1.getTime()));

        }
        return result;
    }

    public SendResult queryControllerConfig(Controller controller,StringBuilder builder,String joinId) throws IOException {

        QueryControllerConfig queryControllerConfig=new QueryControllerConfig();
        byte[] buffer = queryControllerConfig.toBuffer(controller.getKzqbsm());
        Date d1=new Date();
        SocketResult result= sendShoot(controller.getKzqdk(),controller.getKzqbsm(), buffer,queryControllerConfig.getId(),joinId);
        Date d2=new Date();
        if(result.getResult() ==SendResult.Success)
        {
            Controller model=queryControllerConfig.toModel(result.getReceive());
            controller.setKzy(model.getKzy());
            controller.setWdbj(model.getWdbj());
            controller.setKzqldkg(model.getKzqldkg());
            controller.setSfsyld(model.getSfsyld());
            controller.setWdkz(model.getWdkz());
            controller.setWdld(model.getWdld());
            controller.setLdsc(model.getLdsc());
            controller.setMdsc(model.getMdsc());
            controller.setHdys(model.getHdys());
            controller.setMqys(model.getMqys());
            controller.setHsjsdzsl(model.getHsjsdzsl());
            controller.setSbzt(DeviceStatus.Noraml);
        }
        else
        {
            controller.setKzy(ControllSource.None);
            controller.setWdbj(LampWarningStatus.Close);
            controller.setKzqldkg(LampSwitchStatus.Close);
            controller.setSfsyld(LampRadarStatus.Close);
            controller.setWdkz(ControllerWorkMode.Unknown);
            controller.setWdld(0);
            controller.setLdsc(0);
            controller.setMdsc(0);
            controller.setHdys(0);
            controller.setMqys(0);
            controller.setHsjsdzsl(0);
            controller.setSbzt(DeviceStatus.Error);
        }

        if(builder!=null) {
            builder.append(String.format("查询运行参数->%s 结果:%s 控制源:%s 雾灯控制:%s 雾灯亮度:%d 亮灯时长:%d 灭灯时长:%d 红灯延时:%d 盲区延时:%d 灯组数:%d 雾灯报警:%d 亮度开关:%d 使用雷达:%d 耗时:%d\n"
                    ,controller.getKzqmc(), result.getResult()
                    , controller.getKzy()
                    , controller.getWdkz(), controller.getWdld(), controller.getLdsc(), controller.getMdsc(), controller.getHdys(), controller.getMqys(), controller.getHsjsdzsl()
                    , controller.getWdbj(), controller.getKzqldkg(), controller.getSfsyld(),d2.getTime()-d1.getTime()));
        }
        controller.setWdlddj(getWdlddj(controller.getWdld()));
        controller.setSspl(getSspl(controller.getLdsc(),controller.getMdsc()));
        controller.setZkb(getZkb(controller.getLdsc(),controller.getMdsc()));

        controller.setWdkzsm(codeService.getCodeValue(CodeType.Wdkz, controller.getWdkz()));
        controller.setSbztsm(codeService.getCodeValue(CodeType.Sbzt, controller.getSbzt()));
        controller.setKzysm(codeService.getCodeValue(CodeType.Kzqly, controller.getKzy()));
        controller.setWdlddjsm(codeService.getCodeValue(CodeType.Wdlddj, controller.getWdlddj()));
        controller.setSsplsm(codeService.getCodeValue(CodeType.Sspl, controller.getSspl()));
        controller.setZkbsm(codeService.getCodeValue(CodeType.Zkb, controller.getZkb()));
        return result.getResult();
    }

    /**
     * 查询控制器基本参数
     * @param controller 控制器
     * @return 查询成功返回控制器，否则返回null
     * @throws IOException
     */
    public Controller queryController(Controller controller) throws IOException {
        String joinId=UUID.randomUUID().toString();
        StringBuilder contentBuilder = new StringBuilder();

        contentBuilder.append(String.format("查询控制器 %d %d",controller.getKzqbsm(),controller.getKzqdk()));

        //基本信息
        QueryController queryControllerStatus=new QueryController();
        byte[] buffer = queryControllerStatus.toBuffer(controller.getKzqbsm());
        SocketResult result= sendShoot(controller.getKzqdk(),controller.getKzqbsm(), buffer,queryControllerStatus.getId(),joinId);
        contentBuilder.append(String.format(" 基本状态 %s",result.getResult()));
        if(result.getResult() ==SendResult.Success)
        {
            Controller controllerStatus=queryControllerStatus.toModel(result.getReceive());
            controller.setKsdz(controllerStatus.getKsdz());
            controller.setJsdz(controllerStatus.getJsdz());
            controller.setKsdz1(controllerStatus.getKsdz1());
            controller.setJsdz1(controllerStatus.getJsdz1());
            controller.setKsdz2(controllerStatus.getKsdz2());
            controller.setJsdz2(controllerStatus.getJsdz2());
            controller.setKsdz3(controllerStatus.getKsdz3());
            controller.setJsdz3(controllerStatus.getJsdz3());
            controller.setWdxjjg(controllerStatus.getWdxjjg());
            controller.setSbzt(DeviceStatus.Noraml);
        }
        else
        {
            controller.setKsdz(0);
            controller.setJsdz(0);
            controller.setKsdz1(0);
            controller.setJsdz1(0);
            controller.setKsdz2(0);
            controller.setJsdz2(0);
            controller.setKsdz3(0);
            controller.setJsdz3(0);
            controller.setWdxjjg(0);
            controller.setSbzt(DeviceStatus.Error);
        }

        //版本
        QueryControllerVersion queryControllerVersion=new QueryControllerVersion();
        buffer=queryControllerVersion.toBuffer(controller.getKzqbsm());
        result= sendShoot(controller.getKzqdk(),controller.getKzqbsm(), buffer,queryControllerVersion.getId(),joinId);

        if(result.getResult() ==SendResult.Success)
        {
            controller.setVersion(queryControllerVersion.toModel(result.getReceive()));
            contentBuilder.append(String.format(" 版本-查询成功: %s",controller.getVersion()));
        }
        else
        {
            controller.setVersion("2022/03/18");
            contentBuilder.append(String.format(" 版本-查询失败: %s",controller.getVersion()));
        }
        //运行参数
        queryControllerConfig(controller,contentBuilder,joinId);

        //文字参数
        queryControllerTextConfig(controller,contentBuilder,joinId);

        //文字
        Tuple<Integer,Integer> results=queryControllerText(controller,false,contentBuilder,joinId);
        contentBuilder.append(String.format(" 雾灯文字,正确次数:%d 错误次数:%d\n",results.getItem1(),results.getItem2()));

        controller.setSbztsm(codeService.getCodeValue(CodeType.Sbzt, controller.getSbzt()));
        logService.insertSystemLog(Token.SystemToken, SystemLogType.QueryController,contentBuilder.toString(),joinId);
        return controller;
    }

    /**
     * 设置控制器基本参数
     * @param controller 控制器
     * @return 发送结果
     * @throws IOException
     */
    public SendResult setController(Controller controller) throws IOException {
        String joinId=UUID.randomUUID().toString();
        StringBuilder contentBuilder = new StringBuilder();
        contentBuilder.append(String.format("下发控制器 %d %d %s",controller.getKzqbsm(),controller.getKzqdk(),controller.getVersion()));

        SetControllerInspection setControllerInspection=new SetControllerInspection();
        byte[] buffer = setControllerInspection.toBuffer(controller.getKzqbsm(),controller.getWdxjjg());
        SocketResult result1=sendShoot(controller.getKzqdk(),controller.getKzqbsm(), buffer,setControllerInspection.getId(),joinId);
        contentBuilder.append(String.format(" 定时巡检 %s",result1.getResult()));

        SetLampAddress setLampAddress=new SetLampAddress();
        buffer=setLampAddress.toBuffer(controller.getKzqbsm(),controller);
        SocketResult result2=sendShoot(controller.getKzqdk(),controller.getKzqbsm(), buffer,setLampAddress.getId(),joinId);
        contentBuilder.append(String.format(" 雾灯地址 %s",result2.getResult()));

        SetControllerRadar setControllerRadar=new SetControllerRadar();
        buffer = setControllerRadar.toBuffer(controller.getKzqbsm(), controller.getSfsyld());
        SocketResult result3=sendShoot(controller.getKzqdk(),controller.getKzqbsm(), buffer,setControllerRadar.getId(),joinId);
        contentBuilder.append(String.format(" 雷达 %s",result3.getResult()));

        SetControllerSwitch setControllerSwitch=new SetControllerSwitch();
        buffer = setControllerSwitch.toBuffer(controller.getKzqbsm(), controller.getKzqldkg());
        SocketResult result4=sendShoot(controller.getKzqdk(),controller.getKzqbsm(), buffer,setControllerSwitch.getId(),joinId);
        if(result4.getResult() !=SendResult.Success)
            contentBuilder.append(String.format(" 开关 %s",result4.getResult()));

        SetControllerWarning setControllerWarning=new SetControllerWarning();
        buffer = setControllerWarning.toBuffer(controller.getKzqbsm(), controller.getWdbj());
        SocketResult result5= sendShoot(controller.getKzqdk(),controller.getKzqbsm(), buffer,setControllerWarning.getId(),joinId);
        contentBuilder.append(String.format(" 报警 %s",result5.getResult()));
        Tuple<Integer,Integer> result6=setControllerText(controller,false,contentBuilder,joinId);
        SendResult result7=setControllerTextConfig(controller,contentBuilder,joinId);

        logService.insertSystemLog(Token.SystemToken,SystemLogType.SetController,contentBuilder.toString(),joinId);
        if(result1.getResult()==SendResult.Success
                &&result2.getResult()==SendResult.Success
                &&result3.getResult()==SendResult.Success
                &&result4.getResult()==SendResult.Success
                &&result5.getResult()==SendResult.Success
                &&result6.getItem2()==0
                &&result7==SendResult.Success)
        {
            return SendResult.Success;
        }
        else
        {
            return SendResult.SendFailed;
        }
    }

    /**
     * 设置控制器能见度等级参数
     * @param token token
     * @param controller 控制器
     * @param visibilityScales 能见度等级参数
     * @return 发送结果
     * @throws IOException
     */
    public SocketResult setVisibilityScale(String token,Controller controller, List<VisibilityScale> visibilityScales) throws IOException {
        StringBuilder builder=new StringBuilder();
        String joinId=UUID.randomUUID().toString();
        SetVisibilityConfig setVisibilityConfig=new SetVisibilityConfig();
        byte[] buffer = setVisibilityConfig.toBuffer(controller.getKzqbsm(),visibilityScales);
        SocketResult result= sendShoot(controller.getKzqdk(),controller.getKzqbsm(), buffer,setVisibilityConfig.getId(),joinId);
        builder.append(String.format("设置能见度等级->%s 标识码:%d 结果:%s\n",controller.getKzqmc(),controller.getKzqbsm(),result.getResult()));
        for(VisibilityScale visibilityScale:visibilityScales)
        {
            builder.append(String.format("能见度等级:%d 能见度上限:%d 雾灯亮度:%d 亮灯时长:%d 灭灯时长:%d 红灯延时:%d 盲区延时:%d 红色警示灯数量:%d\n",
                    visibilityScale.getNjddj(),visibilityScale.getNjdsx(),visibilityScale.getWdld(),visibilityScale.getLdsc(),visibilityScale.getMdsc(),visibilityScale.getHdys(),visibilityScale.getMqys(),visibilityScale.getHsjsdzsl()));
        }
        logService.insertSystemLog(token,SystemLogType.SetVisibilityScales,builder.toString(),joinId);
        return result;
    }

    /**
     * 查询控制器能见度等级参数
     * @param kzqbsm 控制器标识码
     * @return 查询成功返回能见度等级参数，否则返回null
     * @throws IOException
     */
    public SocketResult<List<VisibilityScale>> queryVisibilityScale(int dk,int kzqbsm) throws IOException {
        QueryVisibilityConfig queryVisibilityConfig=new QueryVisibilityConfig();
        byte[] buffer=queryVisibilityConfig.toBuffer(kzqbsm);
        SocketResult result=sendShoot(dk,kzqbsm, buffer,queryVisibilityConfig.getId(),null);
        if(result.getResult() ==SendResult.Success)
        {
            result.setData(queryVisibilityConfig.toModel(result.getReceive()));
        }
        return result;
    }

    public SendResult setVisibility(FogArea fogArea,int dk,int kzqbsm,String joinId) throws IOException {
        SetVisibilityStatus setVisibility=new SetVisibilityStatus();
        byte[] buffer=setVisibility.toBuffer(fogArea,kzqbsm);
        return sendShoot1(dk,kzqbsm,buffer,setVisibility.getId(),joinId);
    }

    /**
     * 查询控制器雾灯集合
     * @param kzqbsm 控制器标识码
     * @param ksdz 开始地址
     * @param jsdz 结束地址
     * @param joinId 日志关联编号
     * @return 雾灯集合，无论是否查询成功都会返回对应数量的雾灯
     * @throws IOException
     */
    public Map<Integer,Lamp> queryLamps(int dk,int kzqbsm, int ksdz, int jsdz,String joinId) throws IOException {

        Map<Integer,Lamp> lamps=new HashMap<>();
        int currentKsdz=ksdz;
        int currendJsdz=currentKsdz+19;
        boolean hasSuccess=false;
        while(currendJsdz<=jsdz)
        {
            QueryLampsStatus queryLampsStatus=new QueryLampsStatus();
            byte[] buffer = queryLampsStatus.toBuffer(kzqbsm,currentKsdz,currendJsdz);
            SocketResult result= sendShoot(dk,kzqbsm, buffer,queryLampsStatus.getId(),joinId);
            if(result.getResult() ==SendResult.Success)
            {
                hasSuccess=true;
                int i=0;
                for(Lamp lamp:queryLampsStatus.toModel(result.getReceive()))
                {
                    lamp.setKzqdk(dk);
                    lamps.put(currentKsdz+(i++),lamp);
                }
            }
            else if(result.getResult()==SendResult.Timeout)
            {
                hasSuccess=true;
            }
            //超时不做处理
//            else
//            {
//                for(int i=currentKsdz;i<=currendJsdz;++i)
//                {
//                    Lamp lamp=new Lamp();
//                    lamp.setWdljzt(LampStatus.Disconnection);
//                    lamp.setMzt(LampDoorStatus.Steal);
//                    lamp.setWdzt(LampTemperatureStatus.TooHigh);
//                    lamp.setDyzt(LampVoltageStatus.TooLow);
//                    lamp.setSbpd(LampPairStatus.Disconnection);
//                    lamp.setLedzt(LampLedStatus.Close);
//                    lamp.setLdzt(LampRadarStatus.Close);
//                    lamp.setWdwd(0);
//                    lamp.setXdcdy(0);
//                    lamp.setTyndy(0);
//                    lamp.setSbzt(DeviceStatus.Error);
//                    lamps.put(lamp.getWdbm(),lamp);
//                }
//            }
            currentKsdz+=20;
            currendJsdz=currentKsdz+19;
        }
        if(currentKsdz<=jsdz)
        {
            QueryLampsStatus queryLampsStatus=new QueryLampsStatus();
            byte[] buffer = queryLampsStatus.toBuffer(kzqbsm,currentKsdz,jsdz);
            SocketResult result= sendShoot(dk,kzqbsm, buffer,queryLampsStatus.getId(),joinId);
            if(result.getResult() ==SendResult.Success)
            {
                hasSuccess=true;
                int i=0;
                for(Lamp lamp:queryLampsStatus.toModel(result.getReceive()))
                {
                    lamp.setKzqdk(dk);
                    lamps.put(currentKsdz+(i++),lamp);
                }
            }
            else if(result.getResult()==SendResult.Timeout)
            {
                hasSuccess=true;
            }
//            else
//            {
//                for(int i=currentKsdz;i<=jsdz;++i)
//                {
//                    Lamp lamp=new Lamp();
//                    lamp.setWdljzt(LampStatus.Disconnection);
//                    lamp.setMzt(LampDoorStatus.Steal);
//                    lamp.setWdzt(LampTemperatureStatus.TooHigh);
//                    lamp.setDyzt(LampVoltageStatus.TooLow);
//                    lamp.setSbpd(LampPairStatus.Disconnection);
//                    lamp.setLedzt(LampLedStatus.Close);
//                    lamp.setLdzt(LampRadarStatus.Close);
//                    lamp.setWdwd(0);
//                    lamp.setXdcdy(0);
//                    lamp.setTyndy(0);
//                    lamp.setSbzt(DeviceStatus.Error);
//                    lamps.put(lamp.getWdbm(),lamp);
//                }
//            }
        }
        return hasSuccess?lamps:null;
    }

    /**
     * 查询控制器能见度
     * @param kzqbsm 控制器标识码
     * @param joinId 关联编号
     * @return 查询成功返回能见度，否则返回null
     * @throws IOException
     */
    public SocketResult<FogArea> queryVisibility(int dk,int kzqbsm,String joinId) throws IOException {
        QueryControllerVisibility queryControllerVisibility=new QueryControllerVisibility();
        byte[] buffer = queryControllerVisibility.toBuffer(kzqbsm);
        SocketResult result= sendShoot(dk,kzqbsm, buffer,queryControllerVisibility.getId(),joinId);
        if(result.getResult() ==SendResult.Success)
        {
            result.setData(queryControllerVisibility.toModel(result.getReceive()));

        }
        return result;
    }

    public SocketResult<Integer> queryLight(int dk,int kzqbsm,String joinId) throws IOException {
        QueryLight queryLight=new QueryLight();
        byte[] buffer = queryLight.toBuffer(kzqbsm);
        SocketResult result= sendShoot(dk,kzqbsm, buffer,queryLight.getId(),joinId);
        if(result.getResult() ==SendResult.Success)
        {
            result.setData(queryLight.toModel(result.getReceive()));
        }
        return result;
    }

    public Controller queryControllerTimer(int dk,int kzqbsm) throws IOException {
        Controller controller=new Controller();
        QueryControllerTimer queryController=new QueryControllerTimer();
        byte[] buffer = queryController.toBuffer(kzqbsm,1);
        SocketResult result= sendShoot(dk,kzqbsm, buffer,queryController.getId(),null);
        if(result.getResult() ==SendResult.Success) {
            Controller temp = queryController.toModel(result.getReceive());
            controller.setReadSuccess1(true);
            controller.setStartHour1(temp.getStartHour1());
            controller.setStartMinute1(temp.getStartMinute1());
            controller.setStopHour1(temp.getStopHour1());
            controller.setStopMinute1(temp.getStopMinute1());
            controller.setMonth1(temp.getMonth1());
            controller.setDay1(temp.getDay1());
            controller.setWdkz1(temp.getWdkz1());
            controller.setWdld1(temp.getWdld1());
            controller.setZkb1(temp.getZkb1());
            controller.setHdys1(temp.getHdys1());
            controller.setMqys1(temp.getMqys1());
            controller.setHsjsdzsl1(temp.getHsjsdzsl1());
            controller.setSfsyxl1(temp.isSfsyxl1());
        }
        else
        {
            controller.setReadSuccess1(false);
            controller.setStartHour1(0);
            controller.setStartMinute1(0);
            controller.setStopHour1(0);
            controller.setStopMinute1(0);
            controller.setMonth1(1);
            controller.setDay1(1);
            controller.setWdkz1(1);
            controller.setWdld1(1);
            controller.setZkb1(1);
            controller.setHdys1(1);
            controller.setMqys1(1);
            controller.setHsjsdzsl1(1);
            controller.setSfsyxl1(false);
        }
        controller.setZkb1sm(codeService.getCodeValue(CodeType.Zkb,controller.getZkb1()));
        controller.setWdkz1sm(codeService.getCodeValue(CodeType.Wdkz,controller.getWdkz1()));

        buffer = queryController.toBuffer(kzqbsm,2);
        result= sendShoot(dk,kzqbsm, buffer,queryController.getId(),null);
        if(result.getResult() ==SendResult.Success) {
            Controller temp = queryController.toModel(result.getReceive());
            controller.setReadSuccess2(true);
            controller.setStartHour2(temp.getStartHour2());
            controller.setStartMinute2(temp.getStartMinute2());
            controller.setStopHour2(temp.getStopHour2());
            controller.setStopMinute2(temp.getStopMinute2());
            controller.setMonth2(temp.getMonth2());
            controller.setDay2(temp.getDay2());
            controller.setWdkz2(temp.getWdkz2());
            controller.setWdld2(temp.getWdld2());
            controller.setZkb2(temp.getZkb2());
            controller.setHdys2(temp.getHdys2());
            controller.setMqys2(temp.getMqys2());
            controller.setHsjsdzsl2(temp.getHsjsdzsl2());
            controller.setSfsyxl2(temp.isSfsyxl2());
        }
        else
        {
            controller.setReadSuccess2(false);
            controller.setStartHour2(0);
            controller.setStartMinute2(0);
            controller.setStopHour2(0);
            controller.setStopMinute2(0);
            controller.setMonth2(1);
            controller.setDay2(1);
            controller.setWdkz2(1);
            controller.setWdld2(1);
            controller.setZkb2(1);
            controller.setHdys2(1);
            controller.setMqys2(1);
            controller.setHsjsdzsl2(1);
            controller.setSfsyxl2(false);
        }
        controller.setZkb2sm(codeService.getCodeValue(CodeType.Zkb,controller.getZkb2()));
        controller.setWdkz2sm(codeService.getCodeValue(CodeType.Wdkz,controller.getWdkz2()));

        buffer = queryController.toBuffer(kzqbsm,3);
        result= sendShoot(dk,kzqbsm, buffer,queryController.getId(),null);
        if(result.getResult() ==SendResult.Success) {
            Controller temp = queryController.toModel(result.getReceive());
            controller.setReadSuccess3(true);
            controller.setStartHour3(temp.getStartHour3());
            controller.setStartMinute3(temp.getStartMinute3());
            controller.setStopHour3(temp.getStopHour3());
            controller.setStopMinute3(temp.getStopMinute3());
            controller.setMonth3(temp.getMonth3());
            controller.setDay3(temp.getDay3());
            controller.setWdkz3(temp.getWdkz3());
            controller.setWdld3(temp.getWdld3());
            controller.setZkb3(temp.getZkb3());
            controller.setHdys3(temp.getHdys3());
            controller.setMqys3(temp.getMqys3());
            controller.setHsjsdzsl3(temp.getHsjsdzsl3());
            controller.setSfsyxl3(temp.isSfsyxl3());
        }
        else
        {
            controller.setReadSuccess3(false);
            controller.setStartHour3(0);
            controller.setStartMinute3(0);
            controller.setStopHour3(0);
            controller.setStopMinute3(0);
            controller.setMonth3(1);
            controller.setDay3(1);
            controller.setWdkz3(1);
            controller.setWdld3(1);
            controller.setZkb3(1);
            controller.setHdys3(1);
            controller.setMqys3(1);
            controller.setHsjsdzsl3(1);
            controller.setSfsyxl3(false);
        }
        controller.setZkb3sm(codeService.getCodeValue(CodeType.Zkb,controller.getZkb3()));
        controller.setWdkz3sm(codeService.getCodeValue(CodeType.Wdkz,controller.getWdkz3()));
        return controller;
    }


    /**
     * 查询继电器状态
     * @param jdqbsm 继电器标识码
     * @param joinId 日志关联编号
     * @return 继电器状态
     * @throws IOException
     */
    public SocketResult<Integer> queryRelayStatus(int jdqbsm,String joinId) throws IOException {

        if(jdqbsm==0)
        {
            SocketResult<Integer> sr=new SocketResult<>();
            sr.setData(RelayControlMode.Error);
            return sr;
        }
        QueryRelayStatus queryRelayStatus = new QueryRelayStatus();
        byte[] buffer = queryRelayStatus.toBuffer();
        SocketResult<Integer> result= sendShoot(jdqbsm, buffer,queryRelayStatus.getId(),joinId);
        if(result.getResult() ==SendResult.Success)
        {
            result.setData(queryRelayStatus.toModel(result.getReceive()));
        }
        else
        {
            result.setData(RelayControlMode.Error);
        }
        return result;
    }

    /**
     * 切换到主控制器
     * @param fogArea 雾区
     * @param joinId 日志关联编号
     * @return 发送结果
     * @throws IOException
     */
    public SocketResult setRelayMain(FogArea fogArea,String joinId) throws IOException {
        //断开2
        SetRelayClose setRelayStop = new SetRelayClose();
        byte[] buffer = setRelayStop.toBuffer(2);

        SocketResult result= sendShoot(fogArea.getJdqbsm(), buffer,setRelayStop.getId(),joinId);
        if(result.getResult() ==SendResult.Success)
        {
            //断开1
            buffer = setRelayStop.toBuffer(1);
            result= sendShoot(fogArea.getJdqbsm(), buffer,setRelayStop.getId(),joinId);
        }
        return result;
    }

    /**
     * 切换到备用控制器
     * @param fogArea 雾区
     * @param joinId 日志关联编号
     * @return 发送结果
     * @throws IOException
     */
    public SocketResult setRelayBak(FogArea fogArea,String joinId) throws IOException {

        //断开2
        SetRelayClose setRelayClose = new SetRelayClose();
        byte[] buffer = setRelayClose.toBuffer(2);
        SocketResult result= sendShoot(fogArea.getJdqbsm(), buffer,setRelayClose.getId(),joinId);
        if(result.getResult() ==SendResult.Success)
        {
            //吸合1
            SetRelayOpen setRelayStart = new SetRelayOpen();
            buffer = setRelayStart.toBuffer(1);
            result=sendShoot(fogArea.getJdqbsm(), buffer,setRelayStart.getId(),joinId);
        }
        return result;
    }

    /**
     * 切换到星历控制器
     * @param fogArea 雾区
     * @param joinId 日志关联编号
     * @return 发送结果
     * @throws IOException
     */
    public SocketResult setRelayOff(FogArea fogArea,String joinId) throws IOException {
        SetRelayOpen setRelayStart = new SetRelayOpen();
        byte[] buffer = setRelayStart.toBuffer(2);
        SocketResult result=sendShoot(fogArea.getJdqbsm(), buffer,setRelayStart.getId(),joinId);
        return result;
    }

    public String sendCommands(List<Controller> controllers,String command) throws IOException {
        StringBuilder builder=new StringBuilder();
        SimpleDateFormat format=new SimpleDateFormat("HH:mm:ss.SSS");
        for(Controller controller:controllers)
        {
            byte[] temp=Convert.hexToBuffer(command);
            byte[] buffer=new byte[temp.length+2];
            buffer[0]=(byte)0x81;
            buffer[1]=(byte)controller.getKzqbsm();
            System.arraycopy(temp,0,buffer,2,temp.length);
            builder.append(String.format("[%s]发→◇%s□\n",
                    format.format(new Date()),Convert.toHex(buffer," ")));

            SocketResult result=sendShoot(controller.getKzqdk(),controller.getKzqbsm(), buffer,buffer[2],null);

            builder.append(String.format("[%s]收←◆%s\n",
                    format.format(new Date()),Convert.toHex(result.getReceive()," ")));
        }
        return builder.toString();
    }

    public int getWdlddj(int wdld)
    {
        Map<Integer,String> wdlddjs=codeService.getCodeValue(CodeType.Wdlddj);
        for(Map.Entry<Integer,String> entity:wdlddjs.entrySet())
        {
            if(Integer.parseInt(entity.getValue())==wdld)
            {
                return entity.getKey();
            }
        }
        return -1;
    }

    public int getWdld(int wdlddj)
    {
        return Integer.parseInt(codeService.getCodeValue(CodeType.Wdlddj,wdlddj));
    }

    public Tuple<Integer,Integer>getLdsc(int sspl,int zkb)
    {
        int ldsc=0;
        int mdsc=0;
        if(sspl==FlashFrequency.Light)
        {
            ldsc=1000;
            mdsc=0;
        }
        else
        {
            int total=0;
            if(sspl==FlashFrequency.Min30)
            {
                total=2000;
            }
            else if(sspl==FlashFrequency.Min60)
            {
                total=1000;
            }
            else if(sspl==FlashFrequency.Min120)
            {
                total=500;
            }
            else if(sspl==FlashFrequency.Min240)
            {
                total=250;
            }
            if(zkb==RelativeProportion.Half)
            {
                ldsc=total/2;
            }
            else if(zkb==RelativeProportion.One_Third)
            {
                ldsc=total/3;
            }
            else if(zkb==RelativeProportion.Quarter)
            {
                ldsc=total/4;
            }
            mdsc=total-ldsc;
        }
        return new Tuple<>(ldsc,mdsc);
    }

    public int getSspl(int ldsc,int mdsc)
    {
        int sspl=0;
        if(ldsc==1000&&mdsc==0) {
            sspl=FlashFrequency.Light;
        }
        else if(ldsc+mdsc==2000) {
            sspl=FlashFrequency.Min30;
        }
        else if(ldsc+mdsc==1000) {
            sspl=FlashFrequency.Min60;
        }
        else if(ldsc+mdsc==500) {
            sspl=FlashFrequency.Min120;
        }
        else if(ldsc+mdsc==250) {
            sspl=FlashFrequency.Min240;
        }
        else
        {
            sspl=0;
        }
        return sspl;
    }

    public int getZkb(int ldsc,int mdsc)
    {
        int zkb=0;
        int total=ldsc+mdsc;
        if(ldsc==total/2)
        {
            zkb=RelativeProportion.Half;
        }
        else if(ldsc==total/3)
        {
            zkb=RelativeProportion.One_Third;
        }
        else if(ldsc==total/4)
        {
            zkb=RelativeProportion.Quarter;
        }
        else
        {
            zkb=0;
        }
        return zkb;
    }

    public int getWdkz(int kzcl)
    {
        List<Strategy> strategies= strategyDAO.getStrategies();
        for (Strategy s:strategies)
        {
          if(kzcl==s.getClbm())
          {
              return s.getWdkz();
          }
        }
        return -1;
    }
}
